package models

import (
	"errors"
	"fmt"
	"time"

	"go-papers/cache"
	orm "go-papers/database"
	"go-papers/tools"
)

type DictData struct {
	DictCode   int    `gorm:"primary_key;AUTO_INCREMENT" json:"dictCode" example:"1"` //字典编码
	DictSort   string `gorm:"type:int(4);" json:"dictSort"`                           //显示顺序
	DictLabel  string `gorm:"type:varchar(128);" json:"dictLabel"`                    //数据标签
	DictValue  string `gorm:"type:varchar(255);" json:"dictValue"`                    //数据键值
	DictName   string `gorm:"type:varchar(255);" json:"dictName"`                     //字典名称
	DictType   string `gorm:"type:varchar(64);" json:"dictType"`                      //字典类型
	CssClass   string `gorm:"type:varchar(128);" json:"cssClass"`                     //
	ListClass  string `gorm:"type:varchar(128);" json:"listClass"`                    //
	IsDefault  string `gorm:"type:varchar(8);" json:"isDefault"`                      //
	Status     string `gorm:"type:int(1);" json:"status"`                             //状态
	Default    string `gorm:"type:varchar(8);" json:"default"`                        //
	CreateBy   string `gorm:"type:varchar(64);" json:"createBy"`                      //
	UpdateBy   string `gorm:"type:varchar(64);" json:"updateBy"`                      //
	UpdateName string `gorm:"-" json:"updateName"`                                    //
	Remark     string `gorm:"type:varchar(255);" json:"remark"`                       //备注
	Params     string `gorm:"-" json:"params"`
	DataScope  string `gorm:"-" json:"dataScope"`
	BaseModel
}

type DictDataItems struct {
	DictCode  int    `gorm:"primary_key;AUTO_INCREMENT" json:"dictCode" example:"1"` //字典编码
	DictSort  string `gorm:"type:int(4);" json:"dictSort"`                           //显示顺序
	DictLabel string `gorm:"type:varchar(128);" json:"dictLabel"`                    //数据标签
	DictValue string `gorm:"type:varchar(255);" json:"dictValue"`                    //数据键值
	DictName  string `gorm:"type:varchar(255);" json:"dictName"`                     //字典名称
	DictType  string `gorm:"type:varchar(64);" json:"dictType"`                      //字典类型
	CssClass  string `gorm:"type:varchar(128);" json:"cssClass"`                     //
	ListClass string `gorm:"type:varchar(128);" json:"listClass"`                    //
	IsDefault string `gorm:"type:varchar(8);" json:"isDefault"`                      //
}

func (DictData) TableName() string {
	return "sys_dict_data"
}

func (e *DictData) Create() (DictData, error) {
	var doc DictData

	i := 0
	orm.Eloquent.Table(e.TableName()).Where("dict_label=? or (dict_label=? and dict_value = ?)", e.DictLabel, e.DictValue).Count(&i)
	if i > 0 {
		return doc, errors.New("字典标签或者字典键值已经存在！")
	}

	result := orm.Eloquent.Table(e.TableName()).Create(&e)
	if result.Error != nil {
		err := result.Error
		return doc, err
	}
	doc = *e
	return doc, nil
}

func (e *DictData) GetByCode() (DictData, error) {
	var doc DictData

	table := orm.Eloquent.Table(e.TableName())
	if e.DictCode != 0 {
		table = table.Where("dict_code = ?", e.DictCode)
	}
	if e.DictLabel != "" {
		table = table.Where("dict_label = ?", e.DictLabel)
	}
	if e.DictType != "" {
		table = table.Where("dict_type = ?", e.DictType)
	}

	if err := table.First(&doc).Error; err != nil {
		return doc, err
	}
	return doc, nil
}

func (e *DictData) Get() ([]DictData, error) {
	var doc []DictData

	table := orm.Eloquent.Table(e.TableName())
	if e.DictCode != 0 {
		table = table.Where("dict_code = ?", e.DictCode)
	}
	if e.DictLabel != "" {
		table = table.Where("dict_label = ?", e.DictLabel)
	}
	if e.DictType != "" {
		table = table.Where("dict_type = ?", e.DictType)
	}

	if err := table.Order("dict_sort").Find(&doc).Error; err != nil {
		return doc, err
	}
	return doc, nil
}

func (e *DictData) CodeToValue(code string, dictValue string) string {
	ss := dictValue
	list, _ := e.GetSearchPage(code)
	if len(list) > 0 {
		for _, v := range list {
			if v.DictValue == dictValue {
				ss = v.DictLabel
				break
			}
		}
	}
	return ss
}

func (e *DictData) GetSearchPage(code string) ([]DictDataItems, error) {
	var doc []DictDataItems

	//cache 读取 然后返回
	cacheKey := fmt.Sprintf("dict:%s", code)
	if foo, ok := cache.GoLocalCache.Get(cacheKey); ok {
		l, _ := foo.([]DictDataItems)
		return l, nil
	}

	table := orm.Eloquent.Table(e.TableName())
	table = table.Where("dict_type = ?", code)
	table = table.Where("deleted_at IS NULL")
	if err := table.Order("sys_dict_data.dict_sort asc", true).Find(&doc).Error; err != nil {

		// 写入cache
		cache.GoLocalCache.Set(cacheKey, doc, 10*time.Minute)

		return nil, err
	}

	// 写入cache
	cache.GoLocalCache.Set(cacheKey, doc, 10*time.Minute)

	return doc, nil
}

func (e *DictData) GetPage(pageSize int, pageIndex int) ([]DictData, int, error) {
	var doc []DictData

	table := orm.Eloquent.Table(e.TableName())
	table = table.Joins("left join sys_user on sys_user.user_id = sys_dict_data.update_by")
	if e.DictCode != 0 {
		table = table.Where("dict_code = ?", e.DictCode)
	}
	if e.DictType != "" {
		table = table.Where("dict_type like ?", "%"+e.DictType+"%")
	}
	if e.DictName != "" {
		table = table.Where("dict_name like ?", "%"+e.DictName+"%")
	}
	if e.DictLabel != "" {
		table = table.Where("dict_label = ?", e.DictLabel)
	}
	if e.Status != "" {
		table = table.Where("status = ?", e.Status)
	}

	// 数据权限控制
	dataPermission := new(DataPermission)
	dataPermission.UserId, _ = tools.StringToInt(e.DataScope)
	table, err := dataPermission.GetDataScope("sys_dict_data", table)
	if err != nil {
		return nil, 0, err
	}
	var count int
	table.Where("sys_dict_data.deleted_at IS NULL").Count(&count)
	table = table.Select("sys_dict_data.*, sys_user.nick_name as update_name")
	if err := table.Order("sys_dict_data.dict_sort").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
		return nil, 0, err
	}

	return doc, count, nil
}

func (e *DictData) Update(id int) (update DictData, err error) {
	if err = orm.Eloquent.Table(e.TableName()).Where("dict_code = ?", id).First(&update).Error; err != nil {
		return
	}

	if e.DictLabel != "" && e.DictLabel != update.DictLabel {
		return update, errors.New("标签不允许修改！")
	}

	if e.DictValue != "" && e.DictValue != update.DictValue {
		return update, errors.New("键值不允许修改！")
	}

	//参数1:是要修改的数据
	//参数2:是修改的数据
	if err = orm.Eloquent.Table(e.TableName()).Model(&update).Updates(&e).Error; err != nil {
		return
	}
	return
}

func (e *DictData) Delete(id int) (success bool, err error) {
	if err = orm.Eloquent.Table(e.TableName()).Where("dict_code = ?", id).Delete(&DictData{}).Error; err != nil {
		success = false
		return
	}
	success = true
	return
}

func (e *DictData) BatchDelete(id []int) (Result bool, err error) {
	if err = orm.Eloquent.Table(e.TableName()).Where("dict_code in (?)", id).Delete(&DictData{}).Error; err != nil {
		return
	}
	Result = true
	return
}
